package thimeeeee.Model;

//import thimeeeee.Skeleton;

public class Field {
	//A szomszédok tömbje
    //0:fent, 1:lent, 2:balfent, 3:jobbfent, 4:ballent, 5:jobblent
    private Field[] neighbors;
	//A szaglás mértéke
    private int trace = 0;
	//Idő bélyeg
    private double timeStamp;
    //változó, mely azt jelzi, hogy a mező változott-e az előző idle híváshoz képest
    //első körben mindent ki kell rajzolni, így ez kezdetben true
    private boolean changed = true;
	
    //A fielden tárolt elemek tömbje
	ElementBase[] elements;
	

	public Field()
    {
//        Skeleton.Create("Field");
//        Skeleton.StartFunc("Field()");
        neighbors = new Field[6];       //létrehozzuk a szomszédos fieldek tömbjét
//        Skeleton.EndFunc("Field", "void");
    }

    //fgv, amely visszaadja, hogy változott-e az adott field az előző kirajzolás óta
    public boolean HasChanged(){
        return changed;
    }

    //kirajzolás után a changed megint false
    public void UnSetChanged(){
        changed = false;
    }

    //szagnyom beállítása
    public void SetTrace(){
        trace = 20;
    }

    public double GetTimeStamp()
    {
        //visszaadja az időbélyeget (ez a bejáráskor fontos)
        return timeStamp;
    }

    //A szomszédos fieldek lekérése
    public Field[] GetNeighbors()
    {
//		Skeleton.StartFunc("Field.GetNeighbors()");

//        Skeleton.EndFunc("Field.GetNeighbors()", "Field[]");
        return this.neighbors;
	}
    //Egy szomszédos filed lekérése megadott irányban
	public Field GetNeighbor(Direction aD)
    {
//        Skeleton.StartFunc("Field.GetNeighbor()");
        Field temp = null;

        //Az iránynak megfelelően visszadjuk a lekért Fieldet
        if(aD == Direction.up)
        {
            temp = neighbors[0];
        }
        if(aD == Direction.down)
        {
            temp = neighbors[1];
        }
        if(aD == Direction.upleft)
        {
            temp = neighbors[2];
        }
        if(aD == Direction.upright)
        {
            temp = neighbors[3];
        }
        if(aD == Direction.downleft)
        {
            temp = neighbors[4];
        }
        if(aD == Direction.downright)
        {
            temp = neighbors[5];
        }
        
//        Skeleton.EndFunc("Field.GetNeighbor()", "Field");
        return temp;
    }

	//Fielden tárolt elemek lekérése
    public ElementBase[] GetElements()
    {
//		Skeleton.StartFunc("Field.GetElements()");
//        Skeleton.EndFunc("Field.GetElements()", "ElementBase[]");
        return elements;
	}

	//Adott irányban a Field szomszédjának beállítása
    public void SetNeighbor(Field aF, Direction aD)
    {
//        Skeleton.StartFunc("Field.SetNeighbor");

        //Az iránynak megfelelően beállítjuk a megfelelő Fieldet
        if(aD == Direction.up)
        {
            neighbors[0] = aF;
        }
        if(aD == Direction.down)
        {
            neighbors[1] = aF;
        }
        if(aD == Direction.upleft)
        {
            neighbors[2] = aF;
        }
        if(aD == Direction.upright)
        {
            neighbors[3] = aF;
        }
        if(aD == Direction.downleft)
        {
            neighbors[4] = aF;
        }
        if(aD == Direction.downright)
        {
            neighbors[5] = aF;
        }
//        Skeleton.EndFunc("Field.SetNeighbor","void");
	}

	//Elem hozzádasa
    public void AddElement(ElementBase aE)
    {
//		Skeleton.StartFunc("Field.AddElement(ElementBase)");

        //egyelőre 2 elemű tömböt alkalmazunk
        if(elements == null)
        {
            //ha a 0. helyen nincs semmi, akkor oda teszi az új elemet
            elements = new ElementBase[2];
            elements[0] = aE;
        }
        else
        {
            for(int i = 0; i < elements.length; i++)
            {
                if(elements[i] == null)
                {
                    elements[i] = aE;
                    break;
                }
            }
        }
        
        //Ha már van ott valami, akkor akkor leteszi az elem mellé az új elemet
        //Mivel ez csak akkor fut le, amikor lelehet tenni az elemet a helyére
        //ezért nem vizsgáljuk itt meg, hogy letehet e.
        
        aE.MyField = this; //Beállíjuk az elem saját fieldjét
        //változott a mező tartalma
        changed = true;

////        Skeleton.EndFunc("Field.AddElement()", "void");
	}

	//Egy elem kivétele a fielden lévő elemek közül
    public void RemoveElement(ElementBase aE)
    {
//		Skeleton.StartFunc("Field.RemoveElement()");

        //nullcheck!!


        // végig megyünk az elements tömbön
        for(int i = 0; i < elements.length; i++)
        {
            // ha az aktuális indexnél lévő element a törlendő
            if(elements[i] == aE)
            {
                // és az aktuális index nem a legutolsó
                if(i < elements.length - 1) 
                {
                    // erre a helyre másoljuk az utánunk lévőt
                    elements[i] = elements[i+1];
                    // azt pedig kinullázzuk
                    elements[i+1] = null;
                }
                else
                {
                    // az utolsó indexnél vagyunk, tehát szimplán nullázunk
                    elements[i] = null;
                }
            }
        }
        //változott a mező tartalma
        changed = true;

//        Skeleton.EndFunc("Field.RemoveElement()", "void");
	}

	//Üres a Field?
    public boolean IsEmpty()
    {
//		Skeleton.StartFunc("Field.IsEmpty()");

        // ebben tároljuk az aktuális esetet
        boolean temp = true;

        if(elements == null)
        {
            temp = true;
        }
        else
        {
            for(int i = 0; i< elements.length; i++)
            {
                // ha az aktuális elem nem null, akkor nyilván nem üres
                if(elements[i] != null) temp = false;
            }
        }

//        Skeleton.EndFunc("Field.IsEmpty()", "boolean");
        return temp;
	}

	public void Idle(double aTimeStamp)
    {
//		Skeleton.StartFunc("Field.Idle()");

        // ha a kapott timestamp nagyobb, mint az eddigi
        if(this.timeStamp < aTimeStamp)
        {
            // eltároljuk az aktuális timestamp-et
            this.timeStamp = aTimeStamp;

            //szagnyom csökkentése, ha még lehet
            if (trace > 0) trace--;

            // ha az elements tömb nem null és nem üres
            if(!this.IsEmpty())
            {
                // a Field minden elementjén meghívjuk az Idle-t
                for(int i = 0; i<elements.length; i++)
                {
                    if(elements[i] != null) elements[i].Idle(aTimeStamp);
                }
            }
        }
        
//        Skeleton.EndFunc("Field.Idle()", "void");
	}

	//A szagminta lekérése
    public int GetTrace()
    {
//        Skeleton.StartFunc("Field.GetTrace()");
//        Skeleton.EndFunc("Field.GetTrace()", "int");
        // visszaadjuk a TraceValue-t
		return trace;
	}
}